package com.goodfox.web.generic.provide.service.impl;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import com.goodfox.web.generic.provide.annotation.DbField;
import com.goodfox.web.generic.provide.exception.EntityExpType;
import com.goodfox.web.generic.provide.exception.EntityValidateException;
import com.goodfox.web.generic.provide.service.EntityService;
import com.goodfox.web.generic.provide.util.DateUtil;
import com.goodfox.web.generic.provide.util.ParameterUtil;
import com.goodfox.web.generic.provide.util.UUIDUtil;

@Service(value="entityService")
public class EntityServiceImpl implements EntityService{

	/** log4j日志器 */
	private Logger logger=Logger.getLogger(EntityServiceImpl.class);
	
	public List fillEntityList(Map map,Class c,int iSub)throws Exception {
		List<String> fieldList=null;
		Field[] fields=c.getDeclaredFields();
		for(Field f:fields){
			if(fieldList==null){
				DbField df=f.getAnnotation(DbField.class);
				if(df.required() && df.pk()==false){
					if(iSub==0){
						Object obj=map.get(f.getName());
						if(obj!=null){
							if(obj.getClass().equals(String.class)){
								fieldList=new ArrayList<String>();
								fieldList.add(String.valueOf(obj));
							}else if(obj.getClass().equals(List.class) || obj.getClass().equals(ArrayList.class)){
								fieldList=(List<String>)obj;
							}
						}
					}else{
						Object obj=map.get(f.getName()+"*"+iSub);
						if(obj!=null){
							if(obj.getClass().equals(String.class)){
								fieldList=new ArrayList<String>();
								fieldList.add(String.valueOf(obj));
							}else if(obj.getClass().equals(List.class) || obj.getClass().equals(ArrayList.class)){
								fieldList=(List<String>)obj;
							}
						}
					}
				}
			}else{
				break;
			}
		}
		List objList=new ArrayList();
		if(fieldList!=null){
			for(String string:fieldList){
				Object o=c.newInstance();
				objList.add(o);
			}
			for(Field f:fields){
				String showName=f.getName();
				try{
					List<String> valueList=null;
					if(iSub==0){
						Object obj=map.get(f.getName());
						if(obj!=null){
							if(obj.getClass().equals(String.class)){
								valueList=new ArrayList<String>();
								valueList.add(String.valueOf(obj));
							}else if(obj.getClass().equals(List.class) || obj.getClass().equals(ArrayList.class)){
								valueList=(List<String>)obj;
							}
						}
					}else{
						Object obj=map.get(f.getName()+"*"+iSub);
						if(obj!=null){
							if(obj.getClass().equals(String.class)){
								valueList=new ArrayList<String>();
								valueList.add(String.valueOf(obj));
							}else if(obj.getClass().equals(List.class) || obj.getClass().equals(ArrayList.class)){
								valueList=(List<String>)obj;
							}
						}
					}
					for(int i=0;i<objList.size();i++){
						Object o=objList.get(i);
						f.setAccessible(true);
						DbField df=f.getAnnotation(DbField.class);
						showName=df.comment();
						if(df.javaType().equals("EntityList")){
							f.set(o, fillEntityList(map,df.subClass(),i+1));
						}else{
							if(valueList!=null && valueList.size()==fieldList.size()){
								String value=valueList.get(i);
								if(value==null || value.trim().equals("")){
									if(df.pk()){
										f.set(o,UUIDUtil.getUUID());
									}else if(df.required()){
										throw new EntityValidateException(EntityExpType.REQUIRED,showName);
									}
								}else{
									value=value.trim();
									if(df.maxLength()==-1 || getStrLength(value)<=df.maxLength()){
										if(df.javaType().equals("Long")){
											f.set(o, Long.parseLong(value));
										}else if(df.javaType().equals("Double")){
											f.set(o, Double.parseDouble(value));
										}else if(df.javaType().equals("Date")){
											f.set(o, DateUtil.dateFormat(value, df.pattern()));
										}else if(df.javaType().equals("List")){
											try{
												f.set(o, map.get(f.getName()));
											}catch(IllegalArgumentException iaex){
												List list=new ArrayList();
												list.add(map.get(f.getName()));
												f.set(o, list);
											}
										}else{
											f.set(o, value);
										}
									}else{
										throw new EntityValidateException(EntityExpType.LENGTH,showName);
									}
								}
							}else{
								if(df.pk()){
									f.set(o,UUIDUtil.getUUID());
								}else if(df.required()){
									throw new EntityValidateException(EntityExpType.REQUIRED,showName);
								}
							}
						}
					}
				}catch(IllegalArgumentException iaex){
					iaex.printStackTrace();
					throw new EntityValidateException(EntityExpType.DATATYPE,showName);
				}
			}
			logger.debug("objList.size:"+objList.size());
		}
		return objList;
	}

	/**
	 * 填充实体
	 * @param map 页面传过来的参数
	 * @param c 需要填充实体的类
	 * @return
	 * @throws Exception
	 */
	public Object fillEntity(Map map,Class c) throws Exception {
		Object o=c.newInstance();
		Field[] fields=c.getDeclaredFields();
		for(Field f:fields){
			String showName=f.getName();
			try{
				DbField df=f.getAnnotation(DbField.class);
				showName=df.comment();
				String value=null;
				if(map.get(f.getName())!=null){
					value=String.valueOf(map.get(f.getName())).trim();
				}
				if(df!=null){
					f.setAccessible(true);
					if(df.javaType().equals("EntityList")){
						f.set(o, fillEntityList(map,df.subClass(),0));
					}else{
						if(value==null || value.trim().equals("")){
							if(df.pk()){
								f.set(o,UUIDUtil.getUUID());
							}else if(df.required()){
								throw new EntityValidateException(EntityExpType.REQUIRED,showName);
							}
						}else{
							value=value.trim();
							if(df.maxLength()==-1 || getStrLength(value)<=df.maxLength()){
								if(df.javaType().equals("Long")){
									f.set(o, Long.parseLong(value));
								}else if(df.javaType().equals("Double")){
									f.set(o, Double.parseDouble(value));
								}else if(df.javaType().equals("Date")){
									f.set(o, DateUtil.dateFormat(value, df.pattern()));
								}else if(df.javaType().equals("List")){
									try{
										f.set(o, map.get(f.getName()));
									}catch(IllegalArgumentException iaex){
										List list=new ArrayList();
										list.add(map.get(f.getName()));
										f.set(o, list);
									}
								}else{
									f.set(o, value);
								}
							}else{
								throw new EntityValidateException(EntityExpType.LENGTH,showName);
							}
						}
					}
				}
			}catch(IllegalArgumentException iaex){
				logger.error("fillEntity异常："+showName, iaex);
				throw new EntityValidateException(EntityExpType.DATATYPE,showName);
			}
		}
		return o;
	}
	
	/**
	 * 获取字符串字节长度
	 * @param s
	 * @return
	 */
	private int getStrLength(String s){
        s = s.replaceAll("[^\\x00-\\xff]", "**");
        int length = s.length();
        return length;
    }
	
	/**
	 * 填充实体
	 * @param request 请求
	 * @param c 需要填充实体的类
	 * @return
	 * @throws Exception
	 */
	public Object fillEntity(HttpServletRequest request,Class c) throws Exception {
		return fillEntity(fillPageMap(request,null),c);
	}
	
	/**
	 * 填充查询页面Map
	 * @param request 请求
	 * @return
	 * @throws Exception
	 */
	public Map fillQueryMap(HttpServletRequest request,ModelMap model){
		return fillPageMap(request,model);
	}
	/**
	 * 填充页面Map
	 * @param request 请求
	 * @return
	 * @throws Exception
	 */
	public Map fillPageMap(HttpServletRequest request,ModelMap model){
		Map pageMap=new HashMap();
		Set<String> setKey = request.getParameterMap().keySet();
        for(String key:setKey) {
        	String sign="_";
        	if(key.indexOf(".")>0){
        		sign=".";
        	}
        	ArrayList<String> keyList=ParameterUtil.getListForString(key, sign);
        	int index=0;
        	if(keyList.size()!=0){
        		index=keyList.size()-1;
        	}
        	String[] values=request.getParameterValues(key);
    		if(values==null || values.length==0){
    			pageMap.put(keyList.get(index), "");
        		if(model!=null){
        			model.put(key,"");
        		}
    		}else if(values.length>1){
    			List list=new ArrayList();
    			for(String value:values){
    				list.add(value);
    			}
    			pageMap.put(keyList.get(index), list);
        		if(model!=null){
        			model.put(key, values);
        		}
    		}else if(values.length==1){
    			if(keyList.get(index).indexOf("List")>0){
    				List list=new ArrayList();
        			for(String value:values){
        				list.add(value);
        			}
        			pageMap.put(keyList.get(index), list);
            		if(model!=null){
            			model.put(key, values);
            		}
    			}else if(keyList.get(index).indexOf("Array")>0){
    				List list=ParameterUtil.getListForString(values[0].trim(), ";");
        			pageMap.put(keyList.get(index).replaceAll("Array", "List"), list);
    				if(model!=null){
	        			model.put(key, values[0].trim());
	        		}
    			}else{
	    			pageMap.put(keyList.get(index), values[0].trim());
	        		if(model!=null){
	        			model.put(key, values[0].trim());
	        		}
    			}
    		}
        }
        return pageMap;
	}
}
